Problem connecting websocket from c++ compiled with emscripten - c++

Trying to connect to websocket (poco-1.9.0 samples\WebSocketServer) using c++ code compiled with emscripten. Using compiled boost 1.69 and one of common examples to connect to socket.
boost::asio::ssl::context ctxt(context::sslv23_client);
ctxt.set_verify_mode(boost::asio::ssl::verify_none);
boost::asio::io_service svc;
tcp::resolver resolver(svc);
tcp::resolver::query query("127.0.0.1", "9980",
boost::asio::ip::resolver_query_base::numeric_service);
tcp::resolver::iterator i = resolver.resolve(query, ec);
boost::asio::ssl::stream<tcp::socket> s(svc, ctxt);
s.lowest_layer().connect(*i, ec);
s.handshake(boost::asio::ssl::stream<tcp::socket>::client, ec);
Server output is as following
Request from 127.0.0.1:58152: GET / HTTP/1.1
Host: 127.0.0.1:9980
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: http://127.0.0.1:8887
Sec-WebSocket-Version: 13
Sec-WebSocket-Protocol: binary
WebSocket connection established.
Frame received (length=0, flags=0x0).
WebSocket connection closed.
However, this code hangs after handshake. Can it be used this way or it's necessary to use async calls from asio?
Also, if there is any similar example that you know of, please share.

I always tell people who try WebAssembly that...
WebAssembly (in a browser context) is JavaScript.
Even though you code in C/C++ using Emscripten, compiled WebAssembly bytecode is run in a browser's JavaScript engine such as V8. This means that WASM code does not have any special low-level APIs beyond JavaScript APIs. Every system-level functions are emulated using JavaScript.
What does it mean? Low-level socket control such as setting SSL versions and SSL handshaking does not make sense because your WASM code can only make use of JavaScript WebSocket API for networking, thus sockets are handled by the browser, not your WASM code.
Instead, you can use plain BSD sockets. Emscripten will convert the BSD sockets into JavaScript WebSocket. In other words, you can't use Poco library at all.
Like this:
struct sockaddr_in addr;
ing res;
int fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
unsigned long nonblocking = 1;
fcntl(fd, F_SETFL, O_NONBLOCK);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(9980);
if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) != 1) {
perror("inet_pton failed");
finish(EXIT_FAILURE);
}
res = connect(server.fd, (struct sockaddr *)&addr, sizeof(addr));
BTW you are forced to use asynchronous (nonblocking) socket operations only, since it is JS websockets.
Related references:
Introduction to Emscripten Sockets by Jonathan Hale
Emscripten socket test code

Related

C++ Should Any Socket Options Be Set Via setsockopt()? (Simple socket POST request)

Currently in my C++ application I authenticate a client by creating a simple POST request then sending it to my webserver (all data is encrypted during transfer) through the C++ socket then receiving and processing the response. The flow of how I make connection and send/receive response to/from my server is like so:
(error handling and other code has been removed, this is all important code relevant to question)
createSocket = socket(AF_INET, SOCK_STREAM, 0);
connect(createSocket, (struct sockaddr *)&sock_t, sizeof(sock_t));
send(createSocket, POSTRequestSend, strlen(POSTRequestSend), 0);
recv(createSocket, responseBuffer, 6000, 0);
So this works just fine, but my question is should I apply any socket options via setsockopt() to my socket? Being that I am only receiving and sending small pieces of data I was wondering if there are any socket options that could help improve performance or if there are any socket options I in general should be using?
I.e. I've seen some examples of people creating/sending similar requests to mine apply these socket options:
int on = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&on, sizeof(int));
So if I were to add this to my socket code it would look like:
int on = 1;
createSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
setsockopt(createSocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&on, sizeof(int));
connect(createSocket, (struct sockaddr *)&sock_t, sizeof(sock_t));
send(createSocket, POSTRequestSend, strlen(POSTRequestSend), 0);
recv(createSocket, responseBuffer, 6000, 0);
Would there be any benifit to setting these socket options? Or are there any other socket options that I should be using based on me only sending POST request with small amounts of data sent/received.

Native SSL Support for WINAPI

I'm trying to make a simple IRC client, using the Winsock API, to which I want to add SSL support. Currently I just use overlapped socket I/O like this:
SOCKET sock = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0x02, 0x01);
if (!sock)
return;
struct sockaddr_in ircClient;
memcpy(&ircClient.sin_addr, he->h_addr_list[0], he->h_length);
ircClient.sin_family = AF_INET;
ircClient.sin_port = wPort;
WSAEVENT hDataEvent = WSA_INVALID_EVENT;
if (WSAConnect(sock, (sockaddr*)&ircClient, sizeof(ircClient), 0, 0, 0, 0) > 0) {
closesocket(sock);
return;
}
if (wsWSAGetLastError() != 0) {
closesocket(sock);
return;
}
Now, as I understand, for SSL support, I need to do SSL handshake after WSAConnect(). I found old Internet posts saying there are no SSL support in Winsock. It is now is year 2017, and 95% of websites work with SSL. Is there still no way to do this? I have found Using Secure Socket Extensions, but it is not SSL.
I've done years ago some SSL/TLS stuff over standard TCP connections using native windows API, but I'm not familiar with this specific "secure socket extension".
I can recommend using SSPI. It doesn't automatically transform your socket to SSL, but can be used pretty easy for generating SSL request/response/data packets on request.
Look for InitializeSecurityContext for more info.

How to connect multiple TCP IP clients to same server port using c++

I want to connect 2 clients to same server port using TCP IP. I have use the below code before bind:-
// Reuse already binded socket
int reuse=1;
setsockopt(m_iSocketId, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse))
listen(iSocketId, 2);
struct sockaddr clientAddr;
socklen_t length = sizeof(clientAddr);
int firstClientSocket = accept(iSocketId, &clientAddr, &length);
length = sizeof(clientAddr);
int secondClientSocket = accept(iSocketId, &clientAddr, &length);
After this code, you will have two client sockets to work with. Note, however that 'accept' function blocks until some client connects. In general, you should use some aync methods (e.g. select) to handle multiple clients.
SO_REUSEADDR is generally not intended for your purposes. It just tells the system that the listening port can be reused by multiple instances of the server. It's good for debugging, when your app doesn't close the socket properly upon exit. Otherwise the system might hold the port for some time, refusing to bind another socket to it.
And don't forget error handling on listen and accept calls =)
You don't need to set SO_REUSEADDR for this. You don't need to do anything special. Just create and connect as many sockets in the client as you need, and keep calling accept() in the server.

Port to Port data transfer with UDP

I'm working on this project where the source and destination ports are specified for sending a message via a UDP socket in C++. I've got the TCP portion of the project working fine, but I don't understand how to specify both the source and destination ports when setting this up.
The way I would know how to do it is the "receiver" sets up a recvfrom() call, with the port that the "sender" will also use in the sendto() command... but it would need to be the same port.
So, given that I need port x on the "receiver" to talk to port y on the "sender", how would I do that?
Thanks
You can define a source port when you call bind on the sender side. For instance:
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) { /*error*/}
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(source_port); // here
int res = bind(sockfd,(struct sockaddr*)&sin, sizeof(sin));
if (res < 0) { /*error*/}
And the destination port goes into the sockaddr parameter passed to sendto.
If this is one-to-one mapping, i.e. one source talks to one destination, then simply bind(2) the local port and connect(2) to the remote IP and port (contrary to common misconception you can connect UDP sockets). Do that on both sides (with appropriate remote and local IPs/ports of course), and now you can just use recv(2) and send(2) without explicit addressing.
If one side needs to wait for the other to send the first packet, then extract source address/port received with recvfrom(2), and then connect(2) to it.
If, on the other hand, one side acts as a multi-client server, then do same bind(2)/connect(2) dance on the client, but only do bind(2) to local port and then use recvfrom(2)/sendto(2) on the server.
If you need simultaneous duplex communication, then you should use sockets in blocking mode -- fcntl(...O_NONBLOCK...), and use select() to determine if your socket is writable or readable or both. Here is a nice example on how this can be done http://www.lowtek.com/sockets/select.html

poll() with non blocking udp socket

I am trying to make a c++ program work which is written by somebody else. I am having hard time understanding it. I am not even %100 sure that we can use poll() with a UDP socket but the code I am refactoring, is using poll() to read from udp socket as follows:
fd.fd = m_bsocket;
fd.events = POLLIN;
iPollResult = poll(&fd, 1, iTimeout);
if(iPollResult > 0)
{
int iReceivedByteCount = recv(m_bsocket, p_pBuffer, p_iBufferSize, 0);
if(iReceivedByteCount > 0)
{
*p_pReadSize = iReceivedByteCount;
}
else
{
eReturnValue = UDP_READ_ERROR;
}
}
return eReturnValue;
I tried sending udp packets to this program using command line:
echo "123" | nc -u 127.0.0.1 25
It looks like poll() always times out and returns 0, therefore I can not read anything.
I also wrote a small c# program that sends udp datagram, but I can not receive the message. I am wondering what I am doing wrong...
While UDP sockets can be used to connect to another host, they are mostly used "connectionless". Reading your question and comments it makes no sense that you have a connected socket. Instead it should be connectionless as suggested by WouterH in his comment.
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in sin = { 0 };
sin.sin_family = AF_INET;
sin.sin_port = htons(25);
sin.sin_addr.s_addr = INADDR_ANY;
bind(sockfd, (struct sockaddr *) &sin, sizeof(sin));
// Make socket non-blocking if needed
With the above code, whenever someone sends UDP packets to port 25 on any address of your host, your socket will intercept it. Use e.g. poll or select to know when data is available.
You don't need to call connect() as UDP is connectionless. You need to bind() the socket to the IP of the interface you are listening on or 0.0.0.0 (INADDR_ANY) for all interfaces. And when sending to a destination, use sendto().
For completeness: if you call connect() on a UDP socket, you are just setting a default destination for the send() function (then you can use send instead of sendto).
If you want to receive data, you always have to bind() the socket to the interface, or all interfaces. Beware that you will have to verify the source address from the messages you are receiving. So you might want to filter the sender by using recvfrom() and checking the source address.