Bind HTTP connection to specific adapter (Hint: Metered Connection) - c++

Windows 8 and above has setting to make a Wi-Fi (and other) connection to be metered (and have cost attached to it, but irrelevant here). I've used Native Wi-Fi API and WCM APIs to find required information.
With sockets, it is possible to bind, selectively send, and ignoring incoming packets from/to the metered-connection. But, how to do this with WinHTTP APIs?
Some answers on StackOverflow and SuperUser suggest using ForceBindIP, but we cannot simply use it.
If MS Windows has implemented metered connections, ideally there should be some approach to instruct WinHTTP services to not to use specific connections.

Unfortunately, neither WinInet nor WinHTTP natively support what you are asking for.
You would likely have to resort to using the WinSock API bind() function to manually bind a WinInet/WinHTTP session socket to the desired network connection.
Prior to Windows 7, you could get a SOCKET handle from an HINTERNET handle by using InternetQueryOption() with the INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO option. It fills an INTERNET_DIAGNOSTIC_SOCKET_INFO struct with information about the connection, including the actual SOCKET handle.
However, this option is no longer supported in Windows 7 and later. And while it might be possible to track down the SOCKET handle manually with some extra work, I don't think it would do you any good. A socket needs to be bound with bind() before it attempts to connect to a server. The relevant information provided by WinInet/WinHTTP that could be used to hunt down the SOCKET handle is not made available until the connect attempt is in progress. Just prior to connecting, the info is not in the TCP routing tables yet. And one connected, it is too late to re-bind the socket.
So I think you are out of luck on this, unless/until Microsoft exposes a new API to support binding WinInet/WinHTTP sessions, or otherwise expose access to the SOCKET handle again.

Related

Possible to use SSL/TLS without changing Berkeley socket code?

We have an existing legacy C++ app which uses TCP via Berkeley C sockets.
We need to continue using Berkeley sockets in our existing environment but for a second, new environment we need to use SSL/TLS.
I've programmed with openssl before but this application code is.... significant, not easy to change.
Is there a way to achieve SSL without making code changes? (networking, proxies etc)
The answer depends on your needs. To send HTTP requests, you can implement a proxy server that will redirect all incoming requests to their destination by adding ssl / tls functionality. For this method, most likely it will not be possible to find a solution "out of the box". I would recommend using Poco, ServerApplication, HTTPs Client session.
To use protocols that support a permanent connection, it is more logical to set up a secure tunnel, which will add ssl / tls to all incoming packets, and remove it from outgoing packets. For this method it is quite possible to find a solution out of the box. Try using the stunnel / ghostunnel from the recommendations. Also, this option can definitely be implemented using the same Poco library, or using low-level posix sockets and openssl encryption.
Both solutions can be set up on the secondary node by sending packets from the source server to the address of the new node, or on the local machine by sending packets to the loopback address.

How to enable gRPC server to support just one client connection

I'm currently considering to use gRPC for basically inter-process communication between Java app (client) and C++ server. The RPC calls will use functionality from very old C++ code base which is definitely not thread-safe.
Normally the Java client will start more gRPC server instances and have just one connection with each server instance.
Is there any way how to ensure this on the gRPC server to accept just one connection and refuse all other attempts for connection. Otherwise I need to introduce some global lock in the RPC functions to have 100% correct server implementation.
There are plans to provide additional server side APIs that will allow the server to decide whether or not to accept an incoming connection, but this is not done yet. For now, a lock is probably a reasonable option.

Establishing a websocket connection with another server

I'm working on embedding Mongoose into an application, and I need to be able to have the app connect to a server when it starts up. How can I do this? On GitHub, I see examples for receiving connections, but none on how to initialize a connection with another one. Any ideas?
Mongoose is a web server. It is designed to accept incoming connections, not make outgoing ones.
If you want to make outgoing connections, the way forward will depend on what you are connecting to and what protocol(s) it may use.
If you want to make outgoing http or https connections, you could use libcurl.
If some other protocol you may be able to find an appropriate library. Or, you can use operating system layer socket APIs to make your own connection, and implement whatever protocol is required on top of that. Here is an example for Linux, for example.

0MQ - get message ip

First, I want to give thanks for that amazing lib! I love it. A client is connecting himself to a server. The server should save the IP and do stuff with it later on (I really need the IP). I found that answer: http://lists.zeromq.org/pipermail/zeromq-dev/2010-September/006381.html but I don't understand how I get the IP out of the message (a XREP)... I think I am only able to read the ID, but the IP is managed internally by 0MQ. His second solution suggests to send the IP as part of the message, but I don't understand how to get the "public"-IP. I found that post: Get TCP address information in ZeroMQ
is pass bind a service to an ephemeral port, get a full connection endpoint ("tcp://ipaddress:port")
I don't get how this works. Does he mean something like a web-service?
In my opinion, it would be best to get the IP out of 0MQ (it has the IP already). I would even adjust 0MQ for that, if somebody could point to the place where the IP is saved, couldn't find it. The socket types are not that important, at the moment. I would prefer smth REQ-REP like. Thank you!
Summary:
TL;DR answer to your question is: you can't get IP address of the peer that sent a message, using ZeroMQ API.
Explanation:
ZeroMQ does not expose peer IP address because it is irrelevant for the message based communication that ZeroMQ is designed for. When it is possible for ZeroMQ to get IP address of client that is connecting to server (in example using method described here), it is useless. For a longer explanation here is how it works inside ZeroMQ and any other server implementation.
Server side of the connection does not handle connected clients by the means of the hashtable that maps IP to client, but by keeping track of connected "sockets" (socket descriptors) - when a server accepts (using accept()) a connection, it receives from operating system socket descriptor to use to communicate with connected peer. All server has to do is keep that descriptor around to read() from and write() to that client. Another client that connects to server receives another socket descriptor.
To summarize: even if ZeroMQ would be able to provide you with IP of connected peer, you should not depend on it. ZeroMQ hides from you connection management so you can focus on messaging. Connection management includes reconnections, which may result in a change of IP without changing the actual ZeroMQ socket connected on the other side.
So here's an example of why you might want to get the ip address a message was delivered from: we have a server whose job it is to synchronize updates onto occasionally-connected clients (think mobile devices here, though this is an extreme example of a mobile deivce.)
When the mobile unit comes onto the network, it sends a list of it's firmware files to the server via a dealer-router connection. The server has a list of all applicable firmware files; if the client needs an update it will initiate an update via a separate mechanism.
Since the IPs for the devices can (and do) change, we need to know the IP address associated with the mobile device FOR THIS CONNECTION, i.e. right now.
Yes, we absolutely can have the client send it's IP address in the message, but that's a waste of another n bytes of valuable satellite air time, and while not pure evil, is sure annoying. Zmq already has this information, if it didn't have it, it wouldn't be able to generate replies. The address is in the socket data, there's no reason the message couldn't (optionally, for all you guys who use wired networks and think disconnects are the exception) include a reference to the socket structure so you can get the address out of it. Other than pedantic religiosity, which is far too common in zmq.
The way ZeroMQ is designed there's no information provided on the remote IP. As far as I know you have to manage this through your application by sending that information as a message of some sort.
The messages themselves use an IP-agnostic ID which has more to do with the instance of ZeroMQ running than any particular interface. This is because there may be more than one transport method and interface connecting the two instances.

Routing sockets to another port

I have a system where I want to listen to a socket and wait to client connect and then pass the connection to another application that I'll start as soon as the connection is established.
I do not have control on this other application and can only set the port where it will listen, but I want to have one process for each new client.
This is what I'm trying to do:
I've been searching for a solution, but I thing I don't have the right terminology, but I managed to find on Richard Stevens' "Unix Network Programming" something about the AF_ROUTE family of sockets that may be combined with a SOCK_RAW to route a connection to another IP and port. But there's too little documentation about how to use this flag and seems to require superuser privileges (that I want to avoid).
Maybe there's an easier solution but I'm probably using the wrong terms. Is it clear what I want to do?
I don't think you'll be able to just "pass" the socket like you want to, especially if you can't change and recompile "APP". Sockets include various administrative overhead (resource management, etc) that are linked to the process they are owned by. In addition, if you can't recompile APP, there is no way to make it bypass the steps involved with accepting a connection and simple have an already open connected "handed" to it by your router.
However, have you considered simply using router as a pass-through? Basically, have your "Router" process connect via sockets to the each "APP" process it spawns, and simply echo whatever it recieves from the appropriate client to the appropriate APP, and visa versa for APP to client?
This does add overhead, and you will have to manage a small mapping to keep track of which clients go to which apps, but it might work (assuming the APP or client aren't basing any behavior off of the IP address they are connected to, etc). Assuming you can't recompile APP, there might not be too many other options.
The code for this is relatively simple. Your handler for data recieved from APP just looks up the socket for the appropriate app from your mapping, and then does a non blocking send of this data out on it. Likewise the handler for data recieved from client. Depending on how exactly the clients and app behave, you may have to handle a bit of synchronization (if you recieve from both simultaneously).